/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package MeteoCal.utility;

import MeteoCal.manager.InvitationManager;
import MeteoCal.manager.NotificationManager;
import MeteoCal.manager.WeatherManager;
import MeteoCal.entity.Event;
import MeteoCal.entity.Weatherforecast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.ScheduleExpression;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


/**
 *
 * @authors Guttadoro, Iommazzo, Saullo
 */

@Singleton
@Startup
public class WeatherChecker {
    
    @EJB
    private WeatherManager wm;
    @EJB
    private NotificationManager nm;
    @EJB
    private InvitationManager im;
    
    private static final Logger logger = Logger.getLogger(WeatherChecker.class.getName());
    private Client client;
    static String place;
    private Long day;
    
    @Resource 
    private TimerService timerService;
    
    @PostConstruct
    private void constructed() {
        logger.log(Level.INFO, "WeatherChecker creato");
        client = ClientBuilder.newClient();
        ScheduleExpression prova = new ScheduleExpression().second("*/40").minute("*").hour("*");
        timerService.createCalendarTimer(prova, new TimerConfig("", false));
    }
    
    @Timeout
    public void updateWeather() throws MalformedURLException, IOException, JSONException{
        
       List<Weatherforecast> forecasts = wm.findAll();
       
        for(Weatherforecast f: forecasts){
                   
            day = selectWeatherDay(f.getDate()); 
            if(day <0) {
                wm.deleteWeather(f);
            }
            place = f.getCity();

            if (day < 15){
                place = f.getCity();
                String resultWeatherforecast = getForecast(place);
                if (resultWeatherforecast == null){
                    continue;
                }
                Weatherforecast forecast = parseJSON(day, resultWeatherforecast);
                System.out.println(forecast.getCity());

                List<Event> events = wm.findByCityAndDate(f.getCity(), f.getDate()); 
                for(Event e: events){
                      if(!f.getDescription().equals(forecast.getDescription()) && forecast.getDescription()!=null){
                            wm.updateWeather(f, forecast);
                            nm.createNotificationWeather(e);
                            if(/*isBadWeather(f.getDescription()) &&*/ e.getOutdoor()){
                            //Check 1 day
                            if(day == 1){
                                nm.createOneDayNotification(e);
                            //Check 3 days
                            }else if (day == 3){
                                Date suggestedDate = e.getDateBegin();
                                for(int i=1; i<12; i++){ 
                                    day = day + 1;
                                    Weatherforecast forecast2 = parseJSON(day, resultWeatherforecast);
        
                                    //if(!isBadWeather(forecast2.getDescription())){
                                        suggestedDate.setDate(suggestedDate.getDate()+i);
                                        nm.createThreeDaysNotification(e, suggestedDate);
                                        break;
                                    //}
                                    //else {
                                       // nm.createThreeDaysNotification(e, suggestedDate); // controlla
                                       // break;
                                   // }

                                }
                            }
                        }
                    }
                }
            }
        }
        
    }
    
    public String getForecast(String place) throws MalformedURLException, IOException{
    
        String URL_OpenWeatherMap_weather = //jom
            "http://api.openweathermap.org/data/2.5/forecast/daily?q="+place+"&type=json&units=metric&cnt=16"; // jom
        String result = "";
        URL url_weather = new URL(URL_OpenWeatherMap_weather);

        HttpURLConnection httpURLConnection = (HttpURLConnection) url_weather.openConnection();

        if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            InputStreamReader inputStreamReader =
                new InputStreamReader(httpURLConnection.getInputStream());
            BufferedReader bufferedReader =
                new BufferedReader(inputStreamReader, 8192);
            String line = null;
            while((line = bufferedReader.readLine()) != null){
                result += line;
            }

            bufferedReader.close();

   
        }
        if(result.equals("{\"message\":\"\",\"cod\":\"404\"}")){ // jom
            return null;
        }
        return result;
        
    }
    
    public Weatherforecast parseJSON(Long day, String result) throws JSONException{
            
            Weatherforecast forecast = new Weatherforecast();
            String parsedResult = "";
            JSONObject jsonObject = new JSONObject(result);

            parsedResult += "Number of object = " + jsonObject.length() + "\n\n";

            //"city"
            JSONObject JSONObject_city = jsonObject.getJSONObject("city");
            forecast.setCity(JSONObject_city.getString("name"));
            forecast.setResult_country(JSONObject_city.getString("country")); 

            //"weather"
            JSONArray JSONArray_list = jsonObject.getJSONArray("list");
            JSONObject JSONObject_list = JSONArray_list.getJSONObject(Integer.parseInt(day.toString()));
            JSONArray JSONArray_weather = JSONObject_list.getJSONArray("weather");
            if(JSONArray_weather.length() > 0){
                JSONObject JSONObject_weather = JSONArray_weather.getJSONObject(0);
                forecast.setDescription(JSONObject_weather.getString("main")); // togli result main 
                forecast.setResult_description(JSONObject_weather.getString("description"));
                forecast.setResult_icon(JSONObject_weather.getString("icon"));
            }
        
        return forecast;
    
    }
    
    
    public static Long selectWeatherDay(Date date){ 
        Date now;
        now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        Long eventTime = date.getTime();
        Long daysGap = eventTime - now.getTime();    
        daysGap = Math.round(((double)daysGap/(double)(24*3600*1000)));
        return daysGap;
    }
    
    
       
    public static boolean isBadWeather(String weather){
        if(weather == null){
            return false;
        }
        String[] badWeather = {"Shower Rain", "Rain", "Thundestorm", "Snow"}; 
        for(String s: badWeather){
            if (s.equals(weather)) {
                return true;
            }
        }
        return false;
    }
}
